package org.andengine.bulletml.simple;

import java.util.List;

import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;

@Root (name = "action")
public class Action implements ActBasics{
	
	private int mode = 0;
	
	@Attribute (required = true)
	private String label; 
	/*options:	fireBeam - fires giant Laser Beam w/o charge animation)
	 * 			chargeBeam - fires giant Laser Beam w/ charging animation
	 * 			fireBullet - small bullet laser
	 * 			fireFan	- fan-shaped spread;
	 * 			fireRadial - radial burst of bullets
	 * 			fireRing
	 * 			oscBullet - oscillating Shots
	 * 			altFan - alternating fire of fanned shots.
	 * 			altIncFan - altFan + add more shots
	 * 			move - move around. PAth to be specified later.
	 */
	
	@Attribute (required = false, name = "difficulty")
	private String minDifficulty = "EASY";
	
	@Attribute (required = false)
	private String augment = "";
	
	@Attribute (required = false)
	private String priority = "LOW";	
	
	/*
	 * Possible Augments:
	 * dmg[Up/Down]<FLOAT>
	 * invuln
	 * regen<CHAR> [5 = S
	 * regen<INT>
	 */
	
	@Element (name = "recovery", required = false)
	private float recoveryInt = 0.0f; //recovery after firing a round.
	
	@Element (name = "gap", required = false)
	private float firingGap = 0.0f; //In seconds. Used for fireBullet. Gap inbetween firing bullets in a round.

	@Element (name = "fireTime", required = false)
	private float fireContInt = 0; //How long do you fire before resting? Can be used for laserbeams and bullet salvos.
	
	@Element (name = "repeat", required = false)
	private int repeat = 0; //Used for more complicated patterns.
	
	@Element (required = false)
	private float fanAngle = 0;
	
	@Element (required = false)
	private float fanAngleAdd = 15;
	
	@Element (required = false)
	private String fanSpread = "CONSTANT";
	
	@Element (required = false)
	private String rotationDir = "CW";
	
	@Element (name = "radius", required = false)
	private float radialOffset = 0;
	
	@ElementList (required = true, inline = true)
	private List<PointXML> points; //coordinates where the action is affecting
	
	@Element (required = false)
	private int altBound = 1;
		
	@Element (name = "fanRep", required = false)
	private int spcFanRep = 0;
	
	@Element (required = false)
	private String oscStart = "EDGE";
	
	@Element (required = false)
	private String reqs = "TIME"; /* Comma-separated
								   * examples:
								   * UNDERHP%<X>,OVERHP%<X>
								   * OVERHP%<X>
								   * UNDERSECS<X>
								   * OVERSECS<X>
								   * COLRAD<X> (collision radius)
	 							   */

	
	public boolean isSeq = false;
	
	public boolean active = false;
	public float timer = 0.0f;
	
	public int maxBullets = 0; //0 = Infinite
	
	public String getLabel() {
		return label;
	}

	public float getRecovery() {
		return recoveryInt;
	}
	
	public float getFiringGap() {
		return firingGap;
	}

	public float getFiringInt() {
		return fireContInt;
	}
	
	public void setFiringInt(float f) {
		this.fireContInt = f;
	}

	public float getFanAngle() {
		return Math.abs(fanAngle);
	}

	public float getRadialOffset() {
		return Math.abs(radialOffset);
	}

	public final List<PointXML> getPoints() {
		return points;
	}
	
	public String toString(){
		String out = "Label: " + label +
			"\nRecovery Time: " + recoveryInt + " seconds" + 
			"\nFiring Gap: " + firingGap + " seconds " +
			"\nFiring Interval: " + fireContInt + " seconds"
			+"\nPoint(s) Affected:";
		for(PointXML x: points){
			out += "\n" + x.toString();
		}
		return out + "\n";
	}

	public String getFanSpread() {
		return fanSpread;
	}

	public void setAugment(String augment) {
		this.augment = augment;
	}

	public String getAugment() {
		return augment;
	}
	
	public boolean isActive(){
		return mode == 1;
	}
	
	public void toggleAct(){
		mode = (mode+1)%2;
	}

	public int getAltBound() {
		return altBound;
	}

	public String getMinDifficulty() {
		return minDifficulty;
	}
	
	public int getRotDir(){
		if(this.rotationDir.equals("AltCCW") && this.firingGap!=0)
			return (int) Math.pow(-1, Math.round(this.timer/this.getFiringGap()));
		else if(this.rotationDir.equals("AltCW") && this.firingGap!=0)
			return (int) Math.pow(-1, Math.round(this.timer/this.getFiringGap()) + 1);
		else if(this.rotationDir.equals("CCW"))
			return 1;
		else 
			return -1;
	}

	public void setRepeat(int repeat) {
		this.repeat = repeat;
	}

	public int getRepeat() {
		return repeat;
	}

	public void setFanAngleAdd(float fanAngleAdd) {
		this.fanAngleAdd = fanAngleAdd;
	}

	public float getFanAngleAdd() {
		return fanAngleAdd;
	}

	@Override
	public int compareTo(Action arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int compareTo(ActionSeq arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	public String getPriority() {
		return priority;
	}

	public String[] getReqs() {
		return reqs.split(",");
	}

	public void setSpcFanRep(int spcFanRep) {
		this.spcFanRep = spcFanRep;
	}

	public int getSpcFanRep() {
		return spcFanRep;
	}

	public float getOscStart() {
		if(this.oscStart.equals("MID"))
			return (float) Math.asin(.5);
		else
			return 0;
	}

}
